﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AgCIM.Tools.SpatialEncoding.Beidou
{
    /// <summary>
    /// 北斗参考网格位置码（未测试）
    /// </summary>
    public class BeidouSpatialEncodingReferenceCode
    {
        /// <summary>
        /// 获取北斗参考位置码
        /// </summary>
        /// <param name="buildingBox">建筑包围盒</param>
        /// <param name="elementBoundingBox">构件包围盒</param>
        /// <returns>北斗参考位置码</returns>
        public string GetReferenceCode(BeidouBoundingBox buildingBox, BeidouBoundingBox elementBoundingBox)
        {
            var buildingCode = GetBuildingCode(buildingBox);
            var elementCenter = elementBoundingBox.GetCenter();
            var buildingCenter = buildingBox.GetCenter();
            var levelCompute = new BeidouGridCellCompute(buildingBox);
            var levelInfo = levelCompute.JudgeLodMesh();

            if (levelInfo.LevelIndex < 5) return null;

            var indexNum = "ABCDEFG";
            var cellLocationX = buildingCenter.Longitude / levelInfo.GetSplit(0) - (int)(buildingCenter.Longitude / levelInfo.GetSplit(0));
            var cellLocationY = buildingCenter.Latitude / levelInfo.GetSplit(1) - (int)(buildingCenter.Latitude / levelInfo.GetSplit(1));

            var needMinusDistanceX = elementCenter.Longitude > buildingCenter.Longitude
                ? levelInfo.GetSplit(0) * (1 - cellLocationX)
                : levelInfo.GetSplit(0) * cellLocationX;

            var needMinusDistanceY = elementCenter.Latitude > buildingCenter.Latitude
                ? levelInfo.GetSplit(1) * (1 - cellLocationY)
                : levelInfo.GetSplit(1) * cellLocationY;

            var xNumCal = (Math.Abs(elementCenter.Longitude - buildingCenter.Longitude) - needMinusDistanceX) / levelInfo.GetSplit(0);
            var yNumCal = (Math.Abs(elementCenter.Latitude - buildingCenter.Latitude) - needMinusDistanceY) / levelInfo.GetSplit(1);

            var xNum = (int)xNumCal + 1;
            var yNum = (int)yNumCal + 1;

            if (xNum > 8 || yNum > 8) return null;

            var xCode = elementCenter.Longitude > buildingCenter.Longitude ? xNum.ToString() : indexNum[xNum - 1].ToString();
            var yCode = elementCenter.Latitude > buildingCenter.Latitude ? yNum.ToString() : indexNum[yNum - 1].ToString();

            if (elementCenter.Longitude == 0 && elementCenter.Latitude == 0)
            {
                return string.Join("", buildingCode.FinalBeidouCode).ToUpper();
            }
            else
            {
                return string.Join("", buildingCode.FinalBeidouCode).ToUpper() + "-" + xCode + yCode;
            }
        }

        /// <summary>
        /// 获取整个建筑编码
        /// </summary>
        /// <param name="buildingBox">整个建筑包围盒</param>
        /// <returns>包含位置码、高度码和最终北斗编码的对象</returns>
        public BuildingCode GetBuildingCode(BeidouBoundingBox buildingBox)
        {
            var buildingCenter = buildingBox.GetCenter();
            var levelCompute = new BeidouGridCellCompute(buildingBox);
            var levelInfo = levelCompute.JudgeLodMesh();
            var levelIndex = levelInfo.LevelIndex;

            BeidouSpatialEncodingPlanarCode beidouSpatialEncodingPlanarCode = new BeidouSpatialEncodingPlanarCode();
            var planarCode = beidouSpatialEncodingPlanarCode.GetPlanarBeidouCode(
                new[] { buildingCenter.Longitude, buildingCenter.Latitude },
                levelIndex
            );

            BeidouSpatialEncodingHeightCode beidouSpatialEncodingHeightCode = new BeidouSpatialEncodingHeightCode();
            var heightCode = beidouSpatialEncodingHeightCode.GetHeightBeidouCode(
                levelInfo.LongitudeSplit,
                levelIndex,
                buildingCenter.Height
            );

            var finalBeidouCode = new List<string>();

            for (int i = 0; i < planarCode.Count; i++)
            {
                finalBeidouCode.Add(planarCode[i]);
                finalBeidouCode.Add(heightCode.CodeTrans[i]);
            }

            return new BuildingCode
            {
                LocationCode = planarCode,
                HeightCode = heightCode,
                FinalBeidouCode = finalBeidouCode,
                LevelIndex = levelIndex
            };
        }
    }

    public class BuildingCode
    {
        public List<string> LocationCode { get; set; }
        public HeightCodeObject HeightCode { get; set; }
        public List<string> FinalBeidouCode { get; set; }
        public int LevelIndex { get; set; }
    }
}
